package com.navinfo.tripanalysis.common.arithmetic.common;

import com.navinfo.tripanalysis.common.util.GsonUtils;
import com.navinfo.tripanalysis.common.protocol.java.EventDataPb;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 各个算法都依赖的中间缓存数据
 * Created by shen on 2018/3/26.
 */
public class DrivingData implements Serializable {
    private static Logger logger = LoggerFactory.getLogger(DrivingData.class);

    /**
     * 所有算法的公共缓存（当前点和上个点的公共数据）<br/>
     * "commonMap": {
     *     "speedMs": 32.38,					速度（m/s）
     *     "speedKmh": 116, 					速度（km/h）
     *     "acceleratedSpeed": 0.01, 		加速度
     *     "latitude": 123456797, 			纬度
     *     "longitude": 42345686, 			经度
     *     "height": 1130, 					高程
     *     "engineOutputTorque": 12, 		发动机输出扭矩
     *     "rotation": 3551,					转速
     *     "accelerator": 12.0,				油门
     *     "brake": 0,						制动信号
     *     "gear": 9,							档位
     *     "clutchSwitch": 0, 				离合器开关
     *     "realTimeOilConsumption": 6, 	发动机瞬时油耗
     *     "fuelConsumptionRate": 15, 		发动机燃油消耗率
     *     "gpsDirection": 0, 				GPS方向
     *     "gpsTime": 1522721068000, 		GPS时间
     *     "dffDistance": 2299, 				距离差
     *     "dffTime": 71000,					时间差
     *     "dffOil": 296,						油耗差
     *     "lowRotationTime": 0, 			发动机转速低于500持续时间
     *     "terminalId": "15940452871", 	通信号
     *     "lastGpsTime": 1522721068000, 	上个点的GPS时间
     *     "lastRotation": 3551, 			上个点的转速
     *     "lastSpeedMs": 32.38 			上个点的速度（m/s）
     * },
     */
    private CommonData commonData = new CommonData();

    /**
     * 所有算法的事件缓存<br/>
     * "eventData": {
     *     引擎超转速事件（其他事件类似）
     *     "engineOverSpeed": {
     *         "startGpsTime": 1522720713000,		事件开始时间
     *         "startLatitude": 123456792,			开始纬度
     *         "startLongitude": 42345681,			开始经度
     *         "startHeight": 1125,					开始高程
     *         "startSpeed": 106,					开始速度
     *         "startGpsDirection": 0,				开始方向
     *         "stopGpsTime": 0,					事件结束时间
     *         "stopLatitude": 0,					结束纬度
     *         "stopLongitude": 0,					结束经度
     *         "stopHeight": 0,						结束高程
     *         "stopSpeed": 0,						结束速度
     *         "stopGpsDirection": 0,				结束方向
     *         "duration": 0,						持续时间
     *         "event": "engineOverSpeed",			事件类型
     *         "extendField01": 11099,				扩展1
     *         "extendField02": 1440,				扩展2
     *         "extendField03": 0,					扩展3
     *         "extendField04": 0,					扩展4
     *         "extendField05": 0,					扩展5
     *         "extendField06": 0,					扩展6
     *         "extendField07": 0,					扩展7
     *         "extendField08": 0,					扩展8
     *         "extendField09": 0,					扩展9
     *         "extendField10": 0					扩展10
     *     }
     * }
     */
    private Map<EventDataPb.EventType, OuterEventData> eventData = new HashMap<>();

    /**
     * 行程的开始结束基本信息<br/>
     * "tripInfo": {
     *     "startTime": 1.5227205E12,			开始时间
     *     "startLongitude": 1.23456789E8,		开始经度
     *     "startLatitude": 4.2345678E7,		开始纬度
     *     "startHeight": 1122.0,				开始高程
     *     "endTime": 0.0,						结束时间
     *     "endLongitude": 0.0,					结束经度
     *     "endLatitude": 0.0,					结束纬度
     *     "endHeight": 0.0						结束高程
     *     "sendToCDcount": 0,					发往成都的次数
     *     "sendTime": 0						最后一次发送时间
     * },
     */
    private TripInfo tripInfo = new TripInfo();
    /**
     * 所有算法输出的统计结果<br/>
     * "varStatistic": {
     *      引擎超转速变量
     *     "RotationOver": {
     *         "mileage": 11099.0,				引擎超转速行驶距离
     *         "timeMs": 355000,					行驶时长
     *         "oil": 1440.0,						行驶油量
     *         "sumRotation": 22659,				转速之和
     *         "number": 9,						位置点数
     *         "avgRotation": 2517,				平均转速
     *         "maxRotation": 3551,				最大转数
     *         "preOver": true					上个点是否超转速
     *     },
     * }
     */
    private Map<String, Object> outerStatistic = new HashMap<>();

    /**
     * 所有算法输出的事件输出列表
     */
    private List<OuterEventData> outerEvent = new ArrayList<>();

    /**
     * 车辆信息<br/>
     * 轮胎半径、后桥速比、变速箱各挡位速比
     */
    private VehicleInfo vehicleInfo = new VehicleInfo();

    /**
     * 瓦片与区域的对应关系,已废弃，放到整个算法链共享
     */
    private Map<Long,Integer> tileLcMapping;

    /**
     * 行程跨天标识 0:不跨天， 1:第一个行程跨天 2:最后一个行程跨天
     **/
    private int crossDayFlag;

    /**
     * DrivingData最后一次更新日期，格式:YYYYMMDD
     */
    private String updateDay;

    public CommonData getCommonData() {
        return commonData;
    }
    public void setCommonData(CommonData commonData) {
        this.commonData = commonData;
    }

    /**
     * 获取所有进行中的事件缓存
     * @return
     */
    public Map<EventDataPb.EventType, OuterEventData> getEventData() {
        return eventData;
    }
    /**
     * 设置所有进行中的事件缓存
     * @return
     */
    public void setEventData(Map<EventDataPb.EventType, OuterEventData> eventData) {
        this.eventData = eventData;
    }
    /**
     * 获取正在进行中的特定事件缓存
     * @param type
     * @return
     */
    public OuterEventData getEventData(EventDataPb.EventType type) {
        return this.eventData.get(type);
    }
    /**
     * 设置正在进行中特定事件缓存
     * @return
     */
    public void putEventData(OuterEventData data) {
        this.eventData.put(data.getEvent(), data);
    }
    /**
     * 移除正在进行中特定事件缓存
     * @param type
     * @return
     */
    public void removeEventData(EventDataPb.EventType type) {
        this.eventData.remove(type);
    }

    public TripInfo getTripInfo() {
        return tripInfo;
    }
    public void setTripInfo(TripInfo tripInfo) {
        this.tripInfo = tripInfo;
    }

    /**
     * 获取所有算法的统计结果
     * @return
     */
    public Map<String, Object> getOuterStatistic() {
        return outerStatistic;
    }

    /**
     * 设置所有算法的统计结果
     * @param outerStatistic
     */
    public void setOuterStatistic(Map<String, Object> outerStatistic) {
        this.outerStatistic = outerStatistic;
    }

    /**
     * 获取具体算法的统计结果
     * @param objName  缓存的key
     * @param objClazz 缓存的对象类型
     * @return 缓存或创建的objClazz类型的对象
     */
    public Object getOrCreateOuterStatistic(String objName, Class objClazz) {
        Object o = this.outerStatistic.get(objName);
        if (o == null) {
            try {
                o = objClazz.newInstance();
                this.setOuterStatistic(objName, o);
            } catch (Exception e) {
                logger.error("", e);
            }
        }
        if (o instanceof Map) {
            o = GsonUtils.gsonToBean(GsonUtils.gsonString(o), objClazz);
            this.setOuterStatistic(objName, o);
        }
        return o;
    }

    /**
     * 设置具体算法的统计结果
     * @param objName
     * @param obj
     */
    public void setOuterStatistic(String objName, Object obj) {
        this.outerStatistic.put(objName, obj);
    }

    /**
     * 获取所有算法的事件输出列表
     * @return
     */
    public List<OuterEventData> getOuterEvent() {
        return outerEvent;
    }
    /**
     * 设置所有算法的事件输出列表
     * @param outerEvent
     */
    public void setOuterEvent(List<OuterEventData> outerEvent) {
        this.outerEvent = outerEvent;
    }
    /**
     * 将事件缓存放入事件输出列表中
     */
    public void addEventDataToList(OuterEventData data) {
        this.outerEvent.add(data);
    }

    public VehicleInfo getVehicleInfo() {
        return vehicleInfo;
    }

    public void setVehicleInfo(VehicleInfo vehicleInfo) {
        this.vehicleInfo = vehicleInfo;
    }

    public Map<Long, Integer> getTileLcMapping() {
        return tileLcMapping;
    }

    public void setTileLcMapping(Map<Long, Integer> tileLcMapping) {
        this.tileLcMapping = tileLcMapping;
    }

    public int getCrossDayFlag() {
        return crossDayFlag;
    }

    public void setCrossDayFlag(int crossDayFlag) {
        this.crossDayFlag = crossDayFlag;
    }

    public String getUpdateDay() {
        return updateDay;
    }

    public void setUpdateDay(String updateDay) {
        this.updateDay = updateDay;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("OuterStatistic.size():[" + outerStatistic.size() + "],");
        for (String key : outerStatistic.keySet()) {
            Object o = outerStatistic.get(key);
            String p = "";
            if (o != null) {
                p = o.toString();
            }
            sb.append("key:[" + key + "],value:[" + p + "]");
        }
        return sb.toString();
    }

}
